package com.leaf.u.basehttp.http.okimpl;

import android.text.TextUtils;

import com.leaf.u.basehttp.http.inter.ILeafRequest;
import com.leaf.u.basehttp.utils.MD5Tools;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.Request;
import okhttp3.RequestBody;
import okio.ByteString;

/**
 * Created by jesse on 2017/5/27.
 */

public class LeafRequest implements ILeafRequest<Request> {
    private Map<String, Object> params = new HashMap<>();
    private Map<String, String> headers = new HashMap<>();
    private Map<String, Object> extras = new HashMap<>();
    private String url;
    private String method = "GET";
    private ContentType contentType = ContentType.Form;
    private MediaType mediaType = MediaType.parse(FORM);

    public final static String FORM = "application/x-www-form-urlencoded";
    public final static String Multipart = "multipart/form-data";

    public enum ContentType {
        Form,
        Multipart,
        CONTENT_TYPE
    }

    public LeafRequest setContentType(ContentType contentType) {
        if (ContentType.CONTENT_TYPE == contentType)
            throw new IllegalArgumentException(" please call setContentType(String)");
        this.contentType = contentType;
        return this;
    }

    public LeafRequest setContentType(String contentType) {
        if (null == contentType || "".equals(contentType))
            throw new IllegalArgumentException("contentType is null");
        this.contentType = ContentType.CONTENT_TYPE;
        mediaType = MediaType.parse(contentType);
        return this;
    }

    public String method() {
        return method;
    }

    @Override
    public LeafRequest get() {
        method = "GET";
        return this;
    }


    @Override
    public LeafRequest post() {
        method = "POST";
        return this;
    }

    @Override
    public LeafRequest url(String url) {
        this.url = url;
        return this;
    }

    @Override
    public LeafRequest put(String key, String value) {
        params.put(key, value);
        return this;
    }

    @Override
    public LeafRequest put(String key, long value) {
        params.put(key, value);
        return this;
    }

    @Override
    public LeafRequest put(String key, File file) {
        if ("GET".equals(method())) {
            return this;
        }
        params.put(key, file);
        return this;
    }

    @Override
    public LeafRequest array(String key, List<File> file) {
        if ("GET".equals(method())) {
            return this;
        }
        for (int i = 0; i < file.size(); i++) {
            params.put(key + "[" + i + "]", file.get(i));
        }
        return this;
    }

    @Override
    public LeafRequest array(String key, String[] value) {
        if ("GET".equals(method())) {
            return this;
        }
        for (int i = 0; i < value.length; i++) {
            params.put(key + "[" + i + "]", value[i]);
        }
        return this;
    }

    @Override
    public LeafRequest putExtra(String key, Object object) {
        extras.put(key, object);
        return this;
    }

    @Override
    public LeafRequest addHeader(String key, String value) {
        if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value)) {
            return this;
        }
        headers.put(key, value);
        return this;
    }

    @Override
    public Map<String, Object> getParams() {
        return this.params;
    }

    @Override
    public Map<String, String> getHeaders() {
        return this.headers;
    }

    @Override
    public Map<String, Object> getExtras() {
        return this.extras;
    }

    @Override
    public Object getExtra(String key) {
        return extras.get(key);
    }

    @Override
    public String getString(String key) {
        return String.valueOf(params.get(key));
    }

    @Override
    public long getLong(String key) {
        return (long) params.get(key);
    }

    @Override
    public Request build() {
        if ("GET".equals(method())) {
            return buildGet();
        } else {
            switch (contentType) {
                case Form:
                    return buildForm();
                case Multipart:
                    return buildMultipart();
                default:
                    return buildBody();
            }
        }
    }

    private Request buildGet() {
        Request.Builder builder = new Request.Builder().get();
        String url = buildUrl();
//        Log.e("url", url);
        builder.url(url);
        for (Iterator<String> iterator = headers.keySet().iterator(); iterator.hasNext(); ) {
            String key = iterator.next();
            String value = headers.get(key);
            builder.addHeader(key, value);
        }
        return builder.build();
    }


    private Request buildForm() {
        okhttp3.Request.Builder builder = new okhttp3.Request.Builder();
        //添加头部
        Set<String> headerSet = headers.keySet();
        Iterator<String> iterator = headerSet.iterator();
        while (iterator.hasNext()) {
            String name = iterator.next();
            String value = headers.get(name);
            builder.addHeader(name, value);
        }
        FormBody.Builder requestBodyBuild = new FormBody.Builder();
        Set<String> paramsKeys = params.keySet();
        Iterator<String> paramsKeysIterator = paramsKeys.iterator();
        while (paramsKeysIterator.hasNext()) {
            String name = paramsKeysIterator.next();
            Object value = params.get(name);
            if (value instanceof File) {
//                requestBodyBuild.addFormDataPart(name, ((File) value).getName(), RequestBody.create(null, (File) value));
            } else {
                requestBodyBuild.add(name, value.toString());
            }
        }
        Request request = builder.post(requestBodyBuild.build()).url(getUrl()).build();

        return request;
    }

    //POST请求相关
    private Request buildMultipart() {
        okhttp3.Request.Builder builder = new okhttp3.Request.Builder();
        //添加头部
        Set<String> headerSet = headers.keySet();
        Iterator<String> iterator = headerSet.iterator();
        while (iterator.hasNext()) {
            String name = iterator.next();
            String value = headers.get(name);
            builder.addHeader(name, value);
        }
        //
        MultipartBody.Builder requestBodyBuild = new MultipartBody.Builder().setType(MultipartBody.FORM);
        Set<String> paramsKeys = params.keySet();
        Iterator<String> paramsKeysIterator = paramsKeys.iterator();
        while (paramsKeysIterator.hasNext()) {
            String name = paramsKeysIterator.next();
            Object value = params.get(name);
            if (value instanceof File) {
                requestBodyBuild.addFormDataPart(name, ((File) value).getName(), RequestBody.create(null, (File) value));
            } else {
                requestBodyBuild.addFormDataPart(name, value.toString());
            }
        }
        Request request = builder.post(requestBodyBuild.build()).url(getUrl()).build();

        return request;
    }


    private Request buildBody() {
        Request.Builder builder = new Request.Builder();
        builder.url(getUrl());
        for (Iterator<String> iterator = headers.keySet().iterator(); iterator.hasNext(); ) {
            String key = iterator.next();
            String value = headers.get(key);
            builder.addHeader(key, value);
        }
        builder.post(RequestBody.create(this.mediaType, buildParams().toString()));
        return builder.build();
    }

    /**
     * URL 编码
     *
     * @param s
     * @return
     */
    private String encode(String s) {
        try {
            String encode = URLEncoder.encode(s, "UTF-8");
            return encode;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return s;
    }

    //构建Get请求地址
    private String buildUrl() {
        if (params.isEmpty()) {
            return getUrl();
        } else {
            StringBuffer buf = new StringBuffer();
            buf.append(getUrl());
            buf.append("?");
            buf.append(buildParams());
            return buf.toString();
        }
    }

    //构建请请求参数 key=value&key=value..
    private StringBuffer buildParams() {
        StringBuffer buf = new StringBuffer();
        Set<String> keySet = params.keySet();
        Iterator<String> iterator = keySet.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            String value = encode(String.valueOf(params.get(next)));
            buf.append(next + "=" + value);
            if (iterator.hasNext()) {
                buf.append("&");
            }
        }
        return buf;
    }

    public String getUrl() {
        return this.url;
    }

    public String uid() {
        return MD5Tools.MD5(buildUrl());
    }
}
